Free Information Xchange presents: ShadowMaster - CD crack by Static Vengeance Sep 13, 1998 REQUIREMENTS: Hex Editor and full game install W32Dasm if you wish to follow along Shadow Master from Psygnosis is a first person shoot in same vain as Doom, but with a couple of twists! First off, instead of running a round you criuse around in a buggy/land rover. Then you have great graphics with creatures that seemed to be right out of Aliens! Two things that bothered me about this game are first, the CD check! That above all needs to be FiX'ed. Then there's the amount of disk space reqiured for this game. With a complete game install you'll end up filling over 425 megs of your hard disk. We'll see what we can do about that as well. So let's get going: Fire up W32Dasm and disassemble the rmg.exe file. Now go to the menu bar and select refs, then data string refs from the drop down menu. Looking for usefull strings to click on, we really don't find any. So our next method is to search for GetDriveTypeA. This a KERNEL32.DLL call that is used in most of the CD checks I have seen. Either way, you'll find an occurrance that deals with the CD check. Here is what you'll find: * Referenced by a CALL at Addresses: |:00423428 , :00423459 , :004234CD , :004240C1 , :00425269 <-- Call by 10 other routines |:004671D3 , :00467206 , :00468D42 , :004693EC , :004693FE | :004318B0 A03CD25900 mov al, byte ptr [0059D23C] :004318B5 83EC64 sub esp, 00000064 :004318B8 A880 test al, 80 :004318BA 53 push ebx :004318BB 56 push esi :004318BC 57 push edi :004318BD 740C je 004318CB <-- Conditional jump to CD check :004318BF B801000000 mov eax, 00000001 :004318C4 5F pop edi :004318C5 5E pop esi :004318C6 5B pop ebx :004318C7 83C464 add esp, 00000064 :004318CA C3 ret * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:004318BD(C) | * Possible StringData Ref from Data Obj ->"pcextras\circ.cir" <-- Check for this file | :004318CB 68144A4D00 push 004D4A14 :004318D0 E8ABD60500 call 0048EF80 :004318D5 83C404 add esp, 00000004 :004318D8 50 push eax :004318D9 8D442410 lea eax, dword ptr [esp+10] :004318DD 50 push eax :004318DE E8BDD60600 call 0049EFA0 :004318E3 83C408 add esp, 00000008 :004318E6 8D4C240C lea ecx, dword ptr [esp+0C] :004318EA 6A3A push 0000003A :004318EC 51 push ecx :004318ED E83EED0600 call 004A0630 :004318F2 83C408 add esp, 00000008 :004318F5 8D54240C lea edx, dword ptr [esp+0C] :004318F9 C6400100 mov [eax+01], 00 :004318FD 52 push edx * Reference To: KERNEL32.GetDriveTypeA, Ord:00DFh <-- Commonly used in CD checks | :004318FE FF15F073EC00 Call dword ptr [00EC73F0] :00431904 83F805 cmp eax, 00000005 <-- 05 is the value for a CD Rom drive :00431907 0F8585000000 jne 00431992 <-- Not a CD Rom, then jump here * Possible StringData Ref from Data Obj ->"\" | :0043190D BF104A4D00 mov edi, 004D4A10 :00431912 83C9FF or ecx, FFFFFFFF :00431915 33C0 xor eax, eax :00431917 8D54240C lea edx, dword ptr [esp+0C] :0043191B F2 repnz :0043191C AE scasb :0043191D F7D1 not ecx :0043191F 2BF9 sub edi, ecx * Possible StringData Ref from Data Obj ->"rb" <-- Read binary call | :00431921 68CCE14A00 push 004AE1CC :00431926 8BF7 mov esi, edi :00431928 8BD9 mov ebx, ecx :0043192A 8BFA mov edi, edx :0043192C 83C9FF or ecx, FFFFFFFF :0043192F F2 repnz :00431930 AE scasb :00431931 8BCB mov ecx, ebx :00431933 4F dec edi :00431934 C1E902 shr ecx, 02 :00431937 F3 repz :00431938 A5 movsd :00431939 8BCB mov ecx, ebx :0043193B 8D542410 lea edx, dword ptr [esp+10] :0043193F 83E103 and ecx, 00000003 :00431942 F3 repz :00431943 A4 movsb * Possible StringData Ref from Data Obj ->"pcextras\circ.cir" <-- File to check for again | :00431944 BF144A4D00 mov edi, 004D4A14 :00431949 83C9FF or ecx, FFFFFFFF :0043194C F2 repnz :0043194D AE scasb :0043194E F7D1 not ecx :00431950 2BF9 sub edi, ecx :00431952 8BF7 mov esi, edi :00431954 8BD9 mov ebx, ecx :00431956 8BFA mov edi, edx :00431958 83C9FF or ecx, FFFFFFFF :0043195B F2 repnz :0043195C AE scasb :0043195D 8BCB mov ecx, ebx :0043195F 4F dec edi :00431960 C1E902 shr ecx, 02 :00431963 F3 repz :00431964 A5 movsd :00431965 8BCB mov ecx, ebx :00431967 8D442410 lea eax, dword ptr [esp+10] :0043196B 83E103 and ecx, 00000003 :0043196E 50 push eax :0043196F F3 repz :00431970 A4 movsb :00431971 E86AD90600 call 0049F2E0 :00431976 83C408 add esp, 00000008 :00431979 85C0 test eax, eax :0043197B 7415 je 00431992 <-- Take this jump for a fail attempt :0043197D 50 push eax :0043197E E87DD90600 call 0049F300 :00431983 83C404 add esp, 00000004 :00431986 B801000000 mov eax, 00000001 <-- Set up for a passed CD check :0043198B 5F pop edi :0043198C 5E pop esi :0043198D 5B pop ebx :0043198E 83C464 add esp, 00000064 :00431991 C3 ret * Referenced by a (U)nconditional or (C)onditional Jump at Addresses: |:00431907(C), :0043197B(C) | :00431992 5F pop edi :00431993 5E pop esi :00431994 33C0 xor eax, eax <-- Set up for a failed CD check :00431996 5B pop ebx :00431997 83C464 add esp, 00000064 :0043199A C3 ret :0043199B 90 nop This is a very short and simplistic CD Rom check. The only thing you need to do to bypass this CD check is NOP the conditional jump at 4318BD. The game will then call the CD check as many times as it wants to but fall right through and load eax with 00000001 and return. The value of 00000001 means (to Shadowmaster) the CD check passed. A simple two byte patch is all that's required to crack this one. However, there are a other things that need to be addressed with ShadowMaster. The first issue is the amount of hard drive space required for a complete game install. ShadowMaster takes up ~425 megs(!!) on your hard with full music and all the videos. So to free up 202 megs of hard drive space we will need to stop any/all videos from being played. Within W32Dasm, I looked for references to any of the video and didn't find any. However, I found a reference to ".mpg" of which all the game videos are. Double clicking on that ref put me in the middle of this routine: * Referenced by a CALL at Addresses: |:00468AF0 , :00468B20 , :00468B35 , :00468B43 , :00468B69 |:00468B77 , :00468B85 , :00468B93 , :00468BA1 , :00468BD9 |:00468BE7 , :00468BF5 , :00468C03 , :00468C11 | :004689E0 83EC64 sub esp, 00000064 :004689E3 53 push ebx :004689E4 55 push ebp :004689E5 56 push esi :004689E6 57 push edi :004689E7 33DB xor ebx, ebx :004689E9 E892BBFCFF call 00434580 <-- We will make use of this call :004689EE E8ADBDFCFF call 004347A0 :004689F3 E888BBFCFF call 00434580 :004689F8 E8A3BDFCFF call 004347A0 :004689FD A180115200 mov eax, dword ptr [00521180] :00468A02 8B0D84115200 mov ecx, dword ptr [00521184] :00468A08 8B7C2478 mov edi, dword ptr [esp+78] :00468A0C 89442410 mov dword ptr [esp+10], eax :00468A10 894C2414 mov dword ptr [esp+14], ecx :00468A14 83C9FF or ecx, FFFFFFFF :00468A17 33C0 xor eax, eax :00468A19 8D542410 lea edx, dword ptr [esp+10] :00468A1D F2 repnz :00468A1E AE scasb :00468A1F F7D1 not ecx :00468A21 2BF9 sub edi, ecx :00468A23 8BF7 mov esi, edi :00468A25 8BE9 mov ebp, ecx :00468A27 8BFA mov edi, edx :00468A29 83C9FF or ecx, FFFFFFFF :00468A2C F2 repnz :00468A2D AE scasb :00468A2E 8BCD mov ecx, ebp :00468A30 4F dec edi :00468A31 C1E902 shr ecx, 02 :00468A34 F3 repz :00468A35 A5 movsd :00468A36 8BCD mov ecx, ebp :00468A38 8D542410 lea edx, dword ptr [esp+10] :00468A3C 83E103 and ecx, 00000003 :00468A3F F3 repz :00468A40 A4 movsb * Possible StringData Ref from Data Obj ->".mpg" <-- The ref that got us here | :00468A41 BF78115200 mov edi, 00521178 :00468A46 83C9FF or ecx, FFFFFFFF :00468A49 F2 repnz :00468A4A AE scasb :00468A4B F7D1 not ecx :00468A4D 2BF9 sub edi, ecx :00468A4F 8BF7 mov esi, edi :00468A51 8BE9 mov ebp, ecx :00468A53 8BFA mov edi, edx :00468A55 83C9FF or ecx, FFFFFFFF :00468A58 F2 repnz :00468A59 AE scasb :00468A5A 8BCD mov ecx, ebp :00468A5C 4F dec edi :00468A5D C1E902 shr ecx, 02 :00468A60 F3 repz :00468A61 A5 movsd :00468A62 8BCD mov ecx, ebp :00468A64 8D442410 lea eax, dword ptr [esp+10] :00468A68 83E103 and ecx, 00000003 :00468A6B 50 push eax :00468A6C F3 repz :00468A6D A4 movsb :00468A6E E81D43FDFF call 0043CD90 :00468A73 83C404 add esp, 00000004 :00468A76 85C0 test eax, eax :00468A78 7418 je 00468A92 :00468A7A 8D4C2410 lea ecx, dword ptr [esp+10] :00468A7E 51 push ecx :00468A7F E85C650200 call 0048EFE0 :00468A84 83C404 add esp, 00000004 :00468A87 50 push eax :00468A88 E8A3E9FAFF call 00417430 :00468A8D 83C404 add esp, 00000004 :00468A90 8BD8 mov ebx, eax * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:00468A78(C) | :00468A92 E8E9BAFCFF call 00434580 :00468A97 E804BDFCFF call 004347A0 :00468A9C E8DFBAFCFF call 00434580 :00468AA1 E8FABCFCFF call 004347A0 :00468AA6 5F pop edi <-- Idealy I just want to get here :00468AA7 5E pop esi :00468AA8 8BC3 mov eax, ebx :00468AAA 5D pop ebp :00468AAB 5B pop ebx :00468AAC 83C464 add esp, 00000064 :00468AAF C3 ret There are way too many calls to track down and patch, why make 14 patches if you can do the same with less. The idea is just to exit the routine as fast as possible executing as few instructions as possible. I decided to change the very first call to a jump 468AA6. This can be accomplished by calculating the jump's offset, or the displacement. As you will see the correct offset is B8 in hex. Changing the E8 92 BB FC FF to E9 B8 00 00 00 elimenates the playing of the videos. Now you can safely delete the directory "Movies" from the ShadowMaster game directory. Not bad, we just dropped the amount of disk space from 425 megs down to 172 megs. However, if you're willing to give up the music on each of the levels you can get the space required down to a "mere" 60 megs. This means we'll have to track down the routine(s) responsible for playing the level wav files. Looking for a ref to music I found "music\", double clicking this put in this LONG routine: * Referenced by a CALL at Addresses: |:004086E8 , :004089C2 <-- Call by two different routines | :00408700 8B442404 mov eax, dword ptr [esp+04] :00408704 81ECC8000000 sub esp, 000000C8 :0040870A 85C0 test eax, eax :0040870C 740D je 0040871B :0040870E A11CD25900 mov eax, dword ptr [0059D21C] :00408713 85C0 test eax, eax :00408715 0F85E5010000 jne 00408900 * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0040870C(C) | :0040871B A1D055EC00 mov eax, dword ptr [00EC55D0] :00408720 8B15CC55EC00 mov edx, dword ptr [00EC55CC] :00408726 40 inc eax :00408727 A3D055EC00 mov dword ptr [00EC55D0], eax :0040872C 8A0C42 mov cl, byte ptr [edx+2*eax] :0040872F 80F9FF cmp cl, FF :00408732 7504 jne 00408738 :00408734 33C0 xor eax, eax :00408736 EB0A jmp 00408742 * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:00408732(C) | :00408738 80F9FE cmp cl, FE :0040873B 750A jne 00408747 :0040873D B801000000 mov eax, 00000001 * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:00408736(U) | :00408742 A3D055EC00 mov dword ptr [00EC55D0], eax * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0040873B(C) | :00408747 0FBE0442 movsx eax, byte ptr [edx+2*eax] :0040874B 83C0FE add eax, FFFFFFFE :0040874E 83F819 cmp eax, 00000019 :00408751 0F8777010000 ja 004088CE <-- Is offset too high? Then jump here :00408757 33C9 xor ecx, ecx :00408759 8A8838894000 mov cl, byte ptr [eax+00408938] :0040875F FF248D08894000 jmp dword ptr [4*ecx+00408908] <-- Jump through wav file jump table :00408766 A1C0816F00 mov eax, dword ptr [006F81C0] :0040876B 83F804 cmp eax, 00000004 :0040876E 0F875A010000 ja 004088CE <-- Jump to exit section :00408774 FF248554894000 jmp dword ptr [4*eax+00408954] :0040877B A1803FC100 mov eax, dword ptr [00C13F80] :00408780 8D4C2400 lea ecx, dword ptr [esp] :00408784 8BD0 mov edx, eax :00408786 C1E206 shl edx, 06 :00408789 03D0 add edx, eax :0040878B 8D0495C092A700 lea eax, dword ptr [4*edx+00A792C0] :00408792 50 push eax * Possible StringData Ref from Data Obj ->"%sbriefing.wav" <-- Briefing wav files starting here | :00408793 682CB44C00 push 004CB42C :00408798 51 push ecx :00408799 E928010000 jmp 004088C6 :0040879E A1803FC100 mov eax, dword ptr [00C13F80] :004087A3 8D4C2400 lea ecx, dword ptr [esp] :004087A7 8BD0 mov edx, eax :004087A9 C1E206 shl edx, 06 :004087AC 03D0 add edx, eax :004087AE 8D0495C092A700 lea eax, dword ptr [4*edx+00A792C0] :004087B5 50 push eax * Possible StringData Ref from Data Obj ->"%sbrief_f.wav" | :004087B6 681CB44C00 push 004CB41C :004087BB 51 push ecx :004087BC E905010000 jmp 004088C6 :004087C1 A1803FC100 mov eax, dword ptr [00C13F80] :004087C6 8D4C2400 lea ecx, dword ptr [esp] :004087CA 8BD0 mov edx, eax :004087CC C1E206 shl edx, 06 :004087CF 03D0 add edx, eax :004087D1 8D0495C092A700 lea eax, dword ptr [4*edx+00A792C0] :004087D8 50 push eax * Possible StringData Ref from Data Obj ->"%sbrief_g.wav" | :004087D9 680CB44C00 push 004CB40C :004087DE 51 push ecx :004087DF E9E2000000 jmp 004088C6 :004087E4 A1803FC100 mov eax, dword ptr [00C13F80] :004087E9 8D4C2400 lea ecx, dword ptr [esp] :004087ED 8BD0 mov edx, eax :004087EF C1E206 shl edx, 06 :004087F2 03D0 add edx, eax :004087F4 8D0495C092A700 lea eax, dword ptr [4*edx+00A792C0] :004087FB 50 push eax * Possible StringData Ref from Data Obj ->"%sbrief_i.wav" | :004087FC 68FCB34C00 push 004CB3FC :00408801 51 push ecx :00408802 E9BF000000 jmp 004088C6 :00408807 A1803FC100 mov eax, dword ptr [00C13F80] :0040880C 8D4C2400 lea ecx, dword ptr [esp] :00408810 8BD0 mov edx, eax :00408812 C1E206 shl edx, 06 :00408815 03D0 add edx, eax :00408817 8D0495C092A700 lea eax, dword ptr [4*edx+00A792C0] :0040881E 50 push eax * Possible StringData Ref from Data Obj ->"%sbrief_s.wav" | :0040881F 68ECB34C00 push 004CB3EC :00408824 51 push ecx :00408825 E99C000000 jmp 004088C6 * Possible StringData Ref from Data Obj ->"music\" <-- The level music files start here | :0040882A 68E4B34C00 push 004CB3E4 * Possible StringData Ref from Data Obj ->"%sindust.wav" | :0040882F 68D4B34C00 push 004CB3D4 :00408834 E988000000 jmp 004088C1 * Possible StringData Ref from Data Obj ->"music\" | :00408839 68E4B34C00 push 004CB3E4 :0040883E 8D442404 lea eax, dword ptr [esp+04] * Possible StringData Ref from Data Obj ->"%siceplant.wav" | :00408842 68C4B34C00 push 004CB3C4 :00408847 50 push eax :00408848 EB7C jmp 004088C6 * Possible StringData Ref from Data Obj ->"music\" | :0040884A 68E4B34C00 push 004CB3E4 :0040884F 8D4C2404 lea ecx, dword ptr [esp+04] * Possible StringData Ref from Data Obj ->"%sdesert.wav" | :00408853 68B4B34C00 push 004CB3B4 :00408858 51 push ecx :00408859 EB6B jmp 004088C6 * Possible StringData Ref from Data Obj ->"music\" | :0040885B 68E4B34C00 push 004CB3E4 * Possible StringData Ref from Data Obj ->"%sruins.wav" | :00408860 68A8B34C00 push 004CB3A8 :00408865 EB5A jmp 004088C1 * Possible StringData Ref from Data Obj ->"music\" | :00408867 68E4B34C00 push 004CB3E4 :0040886C 8D442404 lea eax, dword ptr [esp+04] * Possible StringData Ref from Data Obj ->"%sforest.wav" | :00408870 6898B34C00 push 004CB398 :00408875 50 push eax :00408876 EB4E jmp 004088C6 * Possible StringData Ref from Data Obj ->"music\" | :00408878 68E4B34C00 push 004CB3E4 :0040887D 8D4C2404 lea ecx, dword ptr [esp+04] * Possible StringData Ref from Data Obj ->"%sendboss.wav" | :00408881 6888B34C00 push 004CB388 :00408886 51 push ecx :00408887 EB3D jmp 004088C6 * Possible StringData Ref from Data Obj ->"music\" | :00408889 68E4B34C00 push 004CB3E4 * Possible StringData Ref from Data Obj ->"%sgeneric1.wav" | :0040888E 6878B34C00 push 004CB378 :00408893 EB2C jmp 004088C1 * Possible StringData Ref from Data Obj ->"music\" | :00408895 68E4B34C00 push 004CB3E4 :0040889A 8D442404 lea eax, dword ptr [esp+04] * Possible StringData Ref from Data Obj ->"%sgeneric2.wav" | :0040889E 6868B34C00 push 004CB368 :004088A3 50 push eax :004088A4 EB20 jmp 004088C6 * Possible StringData Ref from Data Obj ->"music\" | :004088A6 68E4B34C00 push 004CB3E4 :004088AB 8D4C2404 lea ecx, dword ptr [esp+04] * Possible StringData Ref from Data Obj ->"%sgeneric3.wav" | :004088AF 6858B34C00 push 004CB358 :004088B4 51 push ecx :004088B5 EB0F jmp 004088C6 * Possible StringData Ref from Data Obj ->"music\" | :004088B7 68E4B34C00 push 004CB3E4 * Possible StringData Ref from Data Obj ->"%sgeneric4.wav" | :004088BC 6848B34C00 push 004CB348 * Referenced by a (U)nconditional or (C)onditional Jump at Addresses: |:00408834(U), :00408865(U), :00408893(U) | :004088C1 8D542408 lea edx, dword ptr [esp+08] :004088C5 52 push edx * Referenced by a (U)nconditional or (C)onditional Jump at Addresses: |:00408799(U), :004087BC(U), :004087DF(U), :00408802(U), :00408825(U) |:00408848(U), :00408859(U), :00408876(U), :00408887(U), :004088A4(U) |:004088B5(U) | :004088C6 E8D5660900 call 0049EFA0 :004088CB 83C40C add esp, 0000000C * Referenced by a (U)nconditional or (C)onditional Jump at Addresses: |:00408751(C), :0040876E(C) | :004088CE 8D442400 lea eax, dword ptr [esp] :004088D2 50 push eax :004088D3 E8B8440300 call 0043CD90 :004088D8 83C404 add esp, 00000004 :004088DB 85C0 test eax, eax :004088DD 740D je 004088EC :004088DF 8D4C2400 lea ecx, dword ptr [esp] :004088E3 51 push ecx :004088E4 E887AD0700 call 00483670 :004088E9 83C404 add esp, 00000004 * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:004088DD(C) | :004088EC C70514D2590000000000 mov dword ptr [0059D214], 00000000 :004088F6 C70518D2590001000000 mov dword ptr [0059D218], 00000001 * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:00408715(C) | :00408900 81C4C8000000 add esp, 000000C8 :00408906 C3 ret :00408907 90 nop -- Jump table for playing level music and level briefings start here -- :00408908 66874000 DWORD 00408766 <-- Play a briefing wav file :0040890C 2A884000 DWORD 0040882A <-- Play indust.wav file :00408910 39884000 DWORD 00408839 <-- Play iceplant.wav file :00408914 4A884000 DWORD 0040884A <-- Play desert.wav file :00408918 5B884000 DWORD 0040885B <-- Play ruins.wav file :0040891C 67884000 DWORD 00408867 <-- Play forest.wav file :00408920 78884000 DWORD 00408878 <-- Play endboss.wav file :00408924 89884000 DWORD 00408889 <-- Play generic1.wav file :00408928 95884000 DWORD 00408895 <-- Play generic2.wav file :0040892C A6884000 DWORD 004088A6 <-- Play generic3.wav file :00408930 B7884000 DWORD 004088B7 <-- Play generic4.wav file :00408934 CE884000 DWORD 004088CE <-- Jump to the exit section :00408938 00000000000000000000 BYTE 10 DUP(0) :00408942 0000000000 BYTE 5 DUP(0) :00408947 00010203 DWORD 03020100 :0040894A 04050607 DWORD 07060504 :0040894F 0809 WORD 0908 :00408951 0A BYTE 0ah :00408952 8B BYTE 8bh :00408953 FF BYTE ffh :00408954 7B874000 DWORD 0040877B <-- Play briefing.wav file :00408958 9E874000 DWORD 0040879E <-- Play brief_f.wav file :0040895C C1874000 DWORD 004087C1 <-- Play brief_g.wav file :00408960 E4874000 DWORD 004087E4 <-- Play brief_i.wav file :00408964 07884000 DWORD 00408807 <-- Play brief_s.wav file That was the routine responsible for playing the mission briefings and the level music wav files. It's the section of music wav you want to kill, not the mission briefings as they are a vital part of the game. The briefings let you know what to do and what's going on in the game for the next level to be played. So now we need to trace each call and find a good place to make a patch to kill the music. * Referenced by a CALL at Addresses: |:00404ED4 , :00468D51 , :004692F9 <-- Called by 3 different places | :004086A0 8B442404 mov eax, dword ptr [esp+04] :004086A4 8B0DD0D25900 mov ecx, dword ptr [0059D2D0] :004086AA A3C855EC00 mov dword ptr [00EC55C8], eax :004086AF A3CC55EC00 mov dword ptr [00EC55CC], eax :004086B4 83C8FF or eax, FFFFFFFF :004086B7 83F903 cmp ecx, 00000003 :004086BA A3D055EC00 mov dword ptr [00EC55D0], eax :004086BF 740A je 004086CB :004086C1 8B0D1CD25900 mov ecx, dword ptr [0059D21C] :004086C7 85C9 test ecx, ecx :004086C9 7507 jne 004086D2 * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:004086BF(C) | :004086CB 33C0 xor eax, eax :004086CD A3D055EC00 mov dword ptr [00EC55D0], eax * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:004086C9(C) | :004086D2 8B0D803FC100 mov ecx, dword ptr [00C13F80] :004086D8 83F916 cmp ecx, 00000016 :004086DB 7C09 jl 004086E6 :004086DD 8D4408EA lea eax, dword ptr [eax+ecx-16] :004086E1 A3D055EC00 mov dword ptr [00EC55D0], eax * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:004086DB(C) | :004086E6 6A00 push 00000000 :004086E8 E813000000 call 00408700 <-- Call the music "dispatch" routine :004086ED 83C404 add esp, 00000004 :004086F0 C3 ret Time to check out the 3 calls to the above code and see what effect each has. The call that came from 00404ED4 plays the mission briefings so we'll let this one come through. Now lets track down the other two to see what they do: * Referenced by a CALL at Address: |:0046901B | :00468D20 A194D76E00 mov eax, dword ptr [006ED794] :00468D25 56 push esi :00468D26 33F6 xor esi, esi :00468D28 3BC6 cmp eax, esi :00468D2A 8935249D7400 mov dword ptr [00749D24], esi :00468D30 7527 jne 00468D59 <-- Force this jump to kill music :00468D32 C705803FC10015000000 mov dword ptr [00C13F80], 00000015 :00468D3C 8935D0D25900 mov dword ptr [0059D2D0], esi :00468D42 E8698BFCFF call 004318B0 :00468D47 85C0 test eax, eax :00468D49 740E je 00468D59 :00468D4B A114A9A700 mov eax, dword ptr [00A7A914] :00468D50 50 push eax :00468D51 E84AF9F9FF call 004086A0 <-- Play music at flaming skull (start) screen :00468D56 83C404 add esp, 00000004 * Referenced by a (U)nconditional or (C)onditional Jump at Addresses: |:00468D30(C), :00468D49(C) | :00468D59 C705189D740001000000 mov dword ptr [00749D18], 00000001 :00468D63 E818E4FFFF call 00467180 :00468D68 A194D76E00 mov eax, dword ptr [006ED794] :00468D6D 8935189D7400 mov dword ptr [00749D18], esi -- snip non iformational code -- :00468E1C 83F808 cmp eax, 00000008 :00468E1F 750A jne 00468E2B :00468E21 C705803FC10015000000 mov dword ptr [00C13F80], 00000015 * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:00468E1F(C) | :00468E2B 5E pop esi :00468E2C C3 ret If you change the conditional jump at 468D30 to a non conditional jump the music at the main start screen will not be played. This is the flaming skull screen where you can choose to start the game or change options. One down, one to go, so let's lets check out the other call: -- Program code -- :004692E0 E85BB1FCFF call 00434440 :004692E5 A1803FC100 mov eax, dword ptr [00C13F80] :004692EA 8BC8 mov ecx, eax :004692EC C1E106 shl ecx, 06 :004692EF 03C8 add ecx, eax :004692F1 8B148DC093A700 mov edx, dword ptr [4*ecx+00A793C0] :004692F8 52 push edx :004692F9 E8A2F3F9FF call 004086A0 <-- Play level music :004692FE A194D76E00 mov eax, dword ptr [006ED794] :00469303 83C404 add esp, 00000004 :00469306 3BC3 cmp eax, ebx :00469308 740A je 00469314 :0046930A C705589E740001000000 mov dword ptr [00749E58], 00000001 -- Continuing program code -- Simple choice here, just overwrite the call so it will not be made. That takes care of all routines that play music for the different levels. Now you can delete the music subdirectory and save an additional 172 megs of hard drive space. So we started with 425 megs and cut it down to about 60 megs for just the actual game. Everything essential to the game still works and if we had made a bad patch the game self terminates and tells you why. I traced one routine (for the flaming skull) back one level and killed the call at that level. The game came up and asked for the CD and when I hit cancel it self terminated and said it was looking for desert.wav file. Anyways, this one is done and has been completly FiX'ed and can now be played without the CD. 1. Do a complete install (inlcuding videos, music, multiplayer) 2. Make the following edits to the program file: Edit the rmg.exe ============================================= Search for: 74 0C B8 01 00 at offset 199,869 Change to : 90 90 -- -- -- -- Optional: Kill all mpg videos -- Search for: E8 92 BB FC FF at offset 425,449 Change to : E9 B8 00 00 00 -- Optional: Kill Main screen and level music -- Search for: 75 27 C7 05 80 at offset 426,288 Change to : EB -- -- -- -- Search for: E8 A2 F3 F9 FF at offset 427,769 Change to : B8 01 00 00 00 3. Delete the movies directory if you made the kill mpg patch 4. Delete the music directory if you made the kill music patches Static Vengeance